public class Solution {

    // TreeNode class definition
    public static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int val) {
            this.val = val;
        }
    }

    // Method to check if a binary tree is balanced
    public boolean isBalanced(TreeNode root) {
        return height(root) != -1;  // Check if the height function returns -1 (which means unbalanced)
    }

    // Helper function to calculate the height of the tree and check balance
    private int height(TreeNode node) {
        if (node == null) {
            return 0;
        }

        int leftHeight = height(node.left);
        int rightHeight = height(node.right);

        // If the subtree is unbalanced, return -1
        if (leftHeight == -1 || rightHeight == -1 || Math.abs(leftHeight - rightHeight) > 1) {
            return -1;
        }

        // Return the height of the current node (max height of left and right subtree + 1)
        return Math.max(leftHeight, rightHeight) + 1;
    }

    // Main method for testing the solution
    public static void main(String[] args) {
        Solution solution = new Solution();

        // Test Case 1: Balanced Tree
        TreeNode root1 = new TreeNode(3);
        root1.left = new TreeNode(9);
        root1.right = new TreeNode(20);
        root1.right.left = new TreeNode(15);
        root1.right.right = new TreeNode(7);
        System.out.println(solution.isBalanced(root1));  // Expected Output: true

        // Test Case 2: Unbalanced Tree
        TreeNode root2 = new TreeNode(1);
        root2.left = new TreeNode(2);
        root2.right = new TreeNode(2);
        root2.left.left = new TreeNode(3);
        root2.left.right = new TreeNode(3);
        root2.left.left.left = new TreeNode(4);
        root2.left.left.right = new TreeNode(4);
        System.out.println(solution.isBalanced(root2));  // Expected Output: false

        // Test Case 3: Empty Tree
        TreeNode root3 = null;
        System.out.println(solution.isBalanced(root3));  // Expected Output: true
    }
}
